#include <iostream>
#include <cstdio>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#define NUM 1024
#define SIZE 100
#define SPA " "
using namespace std;

char all_order[NUM];
char* single_order[SIZE];
char _env[100];

int main()
{
    extern char** environ;
    while(true)
    {
        // 1.打印出提示信息
        cout << "[dgz@ myshell]$ ";
        // fflush(stdout);
        // 2.获取命令 ls -l -a
        memset(all_order,'\0',sizeof(all_order));
        if(fgets(all_order,sizeof all_order,stdin) == NULL)
        continue;
     
        all_order[strlen(all_order) - 1] = '\0';
        // 如果没有这一步all_order结尾会多带一个'\n',会导致execvp传入vector时多出一个'\n'指令
        // 而这个指令是无效的会造成错误。
        // printf("ehco:%s\n",all_order); -debug
        // 3.将命令分解为 "ls" "-l" "-a"
        single_order[0] = strtok(all_order,SPA);
        int index = 1;
        if(strcmp("ls",single_order[0]) == 0)
        {
            single_order[index++] = "--color=auto";
        }
        if(strcmp("ll",single_order[0]) == 0)
        {
            single_order[0] = "ls";
            single_order[index++] = "-l";
            single_order[index++] = "--color=auto";
        }
        while(single_order[index++] = strtok(NULL,SPA));
        if(strcmp("export",single_order[0]) == 0 && single_order[1] != nullptr)
        {
            strcpy(_env,single_order[1]);
            int ret = putenv(_env);
            if(ret > 0)
            {
                printf("%s export success\n",single_order[1]);
            }
            // for(int i = 0;environ[i];i++)
            // {
            //     printf("[%d]:%s\n",i,environ[i]);
            // }
            continue;
        }
        // 4.内置命令 cd，就是让父进程自己执行的命令，本质就是shell中的一个函数调用
        if(strcmp("cd",single_order[0]) == 0)
        {
            chdir(single_order[1]);
            continue;
        }
        // 5.fork
        pid_t id = fork();
        if(id == 0)
        {
            execvp(single_order[0],single_order);
            // int ret = execvp(single_order[0],single_order);
            // cout << "ret:" << ret << endl;
            exit(1);
        }
        int status = 0;
        pid_t res = waitpid(id,&status,0);
        if(res > 0)
        {
            cout << "exit code status:" << WEXITSTATUS(status) << endl;
        }


    }


    return 0;
}